<template>

  <div class="section" id="step5">
    <h2 class="section-title">学习资源推荐</h2>
    <MdPreview :model-value="stableContent" class="msg"/>
  </div>
  <div class="section">
    <h2 class="section-title">知识图谱</h2>
    <el-button @click="getKnowledgeGraph()" type="info" class="knowledge-graph-btn">
      <el-icon>
        <Connection />
      </el-icon>
      知识图谱
    </el-button>
  <div class="container">
    <div ref="graphPanel" class="graph-panel"></div>
  </div>
</div>
  <div class="section">
    <h2 class="section-title">学习计划推荐</h2>
    <el-button @click="addEvent()" type="primary" class="auto-schedule-btn">
      <el-icon>
        <MagicStick />
      </el-icon>
      自动安排计划
    </el-button>
    <el-button @click="addEventByHand()" type="success" class="manual-add-btn">
      <el-icon>
        <Calendar />
      </el-icon>
      添加计划
    </el-button>
    <ScheduleXCalendar :calendar-app="calendarApp">
    </ScheduleXCalendar>
  </div>

  <div class="section">
    <h2 class="section-title">个性化训练</h2>
    <el-button @click="voiceTraining()" type="primary" class="knowledge-graph-btn">
    <el-icon>
      <MagicStick />
      </el-icon>
        语音训练
      </el-button>
    <p class="button-description">点击即可跳转到语音训练的页面，进行语音训练，提升您的口语表达能力。</p>

    <el-button @click="targetedQuestionTraining()" type="info" class="knowledge-graph-btn">
      <el-icon>
        <Connection />
        </el-icon>
        针对性题目训练
    </el-button>
    <p class="button-description">点击即可跳转到针对性题目训练的页面，开始针对性题目训练，强化知识点掌握。</p>
  </div>


  <el-dialog v-model="dialogVisible" title="添加事件" width="700px" class="custom-event-dialog">
    <template #header>
      <div class="dialog-header">
        <span class="dialog-title">添加事件</span>
      </div>
    </template>

    <el-form :model="eventForm" :rules="rules" ref="formRef" class="event-form">
      <!-- 修改标题输入框，添加"标题"标签 -->
      <el-form-item label="标题" prop="title" class="form-item-with-label">
        <el-input v-model="eventForm.title" placeholder="请输入标题" class="title-input" />
      </el-form-item>

      <div class="time-section">
        <el-form-item label="开始时间" prop="start" class="time-item">
          <el-date-picker v-model="eventForm.start" type="datetime" placeholder="选择开始时间" value-format="YYYY-MM-DD HH:mm"
            :default-time="new Date(0, 0, 0, 8, 0)" class="time-picker" />
        </el-form-item>

        <el-form-item label="结束时间" prop="end" class="time-item">
          <el-date-picker v-model="eventForm.end" type="datetime" placeholder="选择结束时间" value-format="YYYY-MM-DD HH:mm"
            :default-time="new Date(0, 0, 0, 18, 0)" class="time-picker" />
        </el-form-item>
      </div>

      <!-- 修改描述输入框，添加"描述"标签 -->
      <el-form-item label="描述" prop="description" class="form-item-with-label">
        <el-input v-model="eventForm.description" type="textarea" rows="4" placeholder="请输入描述"
          class="description-input" />
      </el-form-item>

      <div class="frequency-section">
        <div class="option-row">
          <span class="option-label">事件发生频率</span>
          <el-select v-model="eventForm.rrule.freq" placeholder="请选择频率" class="frequency-select">
            <el-option label="每日" value="DAILY" />
            <el-option label="每周" value="WEEKLY" />
            <el-option label="每月" value="MONTHLY" />
            <el-option label="每年" value="YEARLY" />
          </el-select>
        </div>

        <div class="frequency-options">
          <div class="option-row">
            <span class="option-label">事件发生次数</span>
            <el-input-number v-model="eventForm.rrule.count" :min="1" controls-position="right" class="number-input" />
          </div>

          <div class="option-row">
            <span class="option-label">事件发生间隔</span>
            <el-input-number v-model="eventForm.rrule.interval" :min="1" controls-position="right"
              class="number-input" />
          </div>
        </div>

        <div class="option-row">
          <span class="option-label">事件发生星期</span>
          <el-select v-model="eventForm.rrule.byDay" multiple placeholder="请选择星期几" class="day-select">
            <el-option label="周一" value="MO" />
            <el-option label="周二" value="TU" />
            <el-option label="周三" value="WE" />
            <el-option label="周四" value="TH" />
            <el-option label="周五" value="FR" />
            <el-option label="周六" value="SA" />
            <el-option label="周日" value="SU" />
          </el-select>
        </div>

        <div class="option-row">
          <span class="option-label">月份日期</span>
          <el-input-number v-model="eventForm.rrule.byMonthDay" :min="1" :max="31" controls-position="right"
            class="number-input" />
        </div>

        <div class="option-row">
          <span class="option-label">截止日期</span>
          <el-date-picker v-model="eventForm.rrule.until" type="date" placeholder="选择截止日期" value-format="YYYYMMDD"
            class="date-picker" />
        </div>

        <div class="option-row">
          <span class="option-label">工作周开始日</span>
          <el-select v-model="eventForm.rrule.wkst" placeholder="请选择工作周开始日" class="day-select">
            <el-option label="周一" value="MO" />
            <el-option label="周二" value="TU" />
            <el-option label="周三" value="WE" />
            <el-option label="周四" value="TH" />
            <el-option label="周五" value="FR" />
            <el-option label="周六" value="SA" />
            <el-option label="周日" value="SU" />
          </el-select>
        </div>
      </div>

      <el-button type="primary" @click="submitForm" class="submit-btn">提交</el-button>
    </el-form>
  </el-dialog>
</template>

<script setup lang="ts">
import { ScheduleXCalendar } from '@schedule-x/vue'
import {
  createCalendar,
  viewMonthAgenda,
  viewMonthGrid,
  viewWeek
} from '@schedule-x/calendar'
import '@schedule-x/theme-default/dist/index.css'
import {createDragAndDropPlugin} from "@schedule-x/drag-and-drop";
import { createEventsServicePlugin } from '@schedule-x/events-service'
import {createScrollControllerPlugin} from "@schedule-x/scroll-controller";
import {createEventRecurrencePlugin} from "@schedule-x/event-recurrence";
import {createEventModalPlugin} from "@schedule-x/event-modal";
import { createResizePlugin } from '@schedule-x/resize'
import { createCurrentTimePlugin } from '@schedule-x/current-time'
import {createCalendarControlsPlugin} from "@schedule-x/calendar-controls";

import {ref, shallowRef, onMounted, onBeforeUnmount } from "vue";
import router from '@/router';
import axios  from 'axios';
import { MdPreview } from 'md-editor-v3'
import { useUserInformationStore } from '@/stores/canUserInformation';
import { useChatWithAIStore } from '@/stores/canChatWithAI';
import { useDrawerVisibleStore } from '@/stores/canDrawerVisible'
import { useButtonVisibleStore } from '@/stores/canButtonVisible'
import { useMessagesStore } from '@/stores/canMessages';
import { useDisplayMessage } from '@/stores/canDisplayMessage';
import { useInterviewResultStore } from '@/stores/canInterviewResult';
import { useInterviewJobStore } from '@/stores/canInterviewJob';


const canUserInformation = useUserInformationStore();
const canChatWithAIStore = useChatWithAIStore();
const canDrawerVisible = useDrawerVisibleStore();
const canButtonVisible = useButtonVisibleStore();
const canMessages = useMessagesStore();
const canDisplayMessage = useDisplayMessage();
const canInterviewResult = useInterviewResultStore();
const canInterviewJob = useInterviewJobStore();

const expressionAnalysis = canInterviewResult.getExpressionAnalysis();
const voiceEvaluation = canInterviewResult.getVoiceEvaluation();
const masteryOfKnowledge = canInterviewResult.getMasteryOfKnowledge();

const eventsService = createEventsServicePlugin();
const calendarControls = createCalendarControlsPlugin();
const eventModal = createEventModalPlugin();

// 新增响应式变量 stableContent
const stableContent = ref('');
let lastContent = '';
let isContentStable = false; // 标记内容是否已稳定

// 定时检查内容是否发生变化
const checkContentChange = () => {
  if (isContentStable) return; // 如果内容已稳定，停止更新

  const currentContent = canMessages.getLastMessage().content;
  if (currentContent !== lastContent) {
    lastContent = currentContent;
    // 不再立即更新stableContent，等待内容稳定
  } else {
    // 内容不再变化，标记为稳定
    isContentStable = true;
    clearInterval(intervalId); // 停止定时器
    // 内容稳定后进行赋值
    stableContent.value = currentContent;
  }
};

// 每隔2秒检查一次内容是否变化
const intervalId = setInterval(checkContentChange, 2000);

// 组件卸载前清理定时器
onBeforeUnmount(() => {
  clearInterval(intervalId);
});

// events 使用 ref，便于后续增删改
const events = ref([
  {
    id: 1000,
    title: '一面 - 张三 (前端开发)',
    start: '2025-07-07 08:00',
    end: '2025-07-07 09:00',
    description: '3年经验，React技术栈',
  },
  {
    id: 2000,
    title: '二面 - 李四 (后端开发)',
    start: '2025-07-09 09:00',
    end: '2025-07-09 12:30',
    description: 'Java工程师，5年经验',
  },
  {
    id: 3000,
    title: '三面 - 王五 (产品经理)',
    start: '2025-07-11 09:30',
    end: '2025-07-11 10:30',
    description: '资深产品，经验丰富',
  }
]);

// 获取当前日期（YYYY-MM-DD格式）
const getCurrentDate = () => {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
};

const calendarApp = shallowRef(createCalendar({
  selectedDate: getCurrentDate(),
  locale: 'zh-CN',
  theme: 'default',
  views: [viewMonthAgenda, viewMonthGrid, viewWeek],
  defaultView: viewWeek.name,
  plugins: [
    eventModal,
    createDragAndDropPlugin(),
    createScrollControllerPlugin({
      initialScroll: '07:45'
    }),
    createEventRecurrencePlugin(),
    eventsService,
    calendarControls,
    createResizePlugin(),
    createCurrentTimePlugin()
  ],
  events: events.value,
  monthGridOptions: {
    nEventsPerDay: 3,
  },
  callbacks: {
    onClickDate(date) {
      calendarControls.setView(viewWeek.name);
      calendarControls.setDate(date);
    },
    onEventUpdate(updatedEvent) {
      // console.log('onEventUpdate', updatedEvent)
    },
  }
}))

onMounted(async() => {
  await getLearningResources();
  await getKnowledgeGraph();
  await getAllEvents();
})

// 添加以下函数用于处理流式数据
const findCompleteJson = (str: string) => {
  let index = 0;
  let braceCount = 0;
  let inString = false;
  let escape = false;

  for (const char of str) {
    if (char === '"' && !escape) {
      inString = !inString;
    } else if (!inString) {
      if (char === '{') {
        braceCount++;
      } else if (char === '}') {
        braceCount--;
        if (braceCount === 0) {
          return { json: str.slice(0, index + 1), endIndex: index + 1 };
        }
      }
    }

    if (char === '\\' && !escape) {
      escape = true;
    } else {
      escape = false;
    }

    index++;
  }

  return { json: null, endIndex: -1 };
};

const processStreamData = async (reader: ReadableStreamDefaultReader<Uint8Array>, decoder: TextDecoder, type: string) => {
  let buffer = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    buffer += decoder.decode(value, { stream: true });

    try {
      const trimmed = buffer.trim();
      if (!trimmed) continue;

      const startIndex = trimmed.indexOf('{');
      if (startIndex === -1) {
        console.warn('buffer中未找到JSON起始符{，跳过处理');
        continue;
      }

      const possibleJson = trimmed.slice(startIndex);
      const result = findCompleteJson(possibleJson);

      if (result.json) {
        // 假设这里有个方法来更新你的Vue状态，例如events数组
        if (type === 'event') {
          const eventItem = JSON.parse(result.json);
          calendarApp.value.eventsService.add(eventItem)
          const displayMessage = `根据已有的事件以及个性化学习资源的推荐，为您新增如下安排：\n- **事件名称**: **${eventItem.title}**\n- **事件开始时间**: ${eventItem.start}\n- **事件结束时间**: ${eventItem.end}\n- **事件描述**: ${eventItem.description}`;
          canDisplayMessage.setDisplayMessage(displayMessage);
        }

        buffer = possibleJson.slice(result.endIndex + 1);
      }
    } catch (e) {
      console.warn('当前buffer无法解析:', e);
    }
  }
};

// 修改后的addEvent方法
function addEvent() {
  canButtonVisible.setButtonVisible(false)
  canDrawerVisible.setDrawerVisible(true)
  canMessages.clearMessages()
  const dataToSend = `根据我面试过程中出现的以下三个方面的问题，给我生成提高的计划安排。表情方面：${expressionAnalysis}。语音方面：${voiceEvaluation}。知识掌握方面：${masteryOfKnowledge}`;
  // const dataToSend = "学习Java"; // 要发送的字符串
  const userInfo = canUserInformation.getUserInfo();
  const apiUrl = 'http://localhost:8080/calendarEvent/addByAI'; // 替换为你的实际接口地址

  canMessages.addMessage({
    role: 'user',
    content: '请根据我的时间安排以及不足之处，帮我生成能够进一步提高自我能力的日程安排'
  });
  canMessages.addMessage({
        role: 'assistant',
        content: ''
  })
  fetch(apiUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ data: dataToSend, userId: userInfo.id })
  }).then(response => {
    const reader = response.body?.getReader();
    const decoder = new TextDecoder();

    if (!reader) {
      console.error('当前响应不支持ReadableStream');
      return;
    }

    processStreamData(reader, decoder, 'event');
  }).catch(error => console.error('请求失败:', error));
}

const dialogVisible = ref(false);
const formRef = ref(null);

const eventForm = ref({
  title: '',
  start: '',
  end: '',
  description: '',
  rrule: {
    freq: '',
    count: null,
    interval: null,
    byDay: [],
    byMonthDay: null,
    until: '',
    wkst: ''
  }
});

const rules = {
  title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
  start: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
  end: [{ required: true, message: '请选择结束时间', trigger: 'change' }],
  description: [{ required: true, message: '请输入描述', trigger: 'blur' }]
};

const addEventByHand = () => {
  dialogVisible.value = true;
};

const submitForm = () => {
  if (!formRef.value) {
    console.error('表单引用不存在');
    return;
  }
  formRef.value.validate((valid :any) => {
    if (valid) {
      // 构建 rrule 字符串
      let rruleParts = [];

      if (eventForm.value.rrule.freq) {
        rruleParts.push(`FREQ=${eventForm.value.rrule.freq}`);
      }

      if (eventForm.value.rrule.count !== null) {
        rruleParts.push(`COUNT=${eventForm.value.rrule.count}`);
      }

      if (eventForm.value.rrule.interval !== null) {
        rruleParts.push(`INTERVAL=${eventForm.value.rrule.interval}`);
      }

      if (eventForm.value.rrule.byDay.length > 0) {
        rruleParts.push(`BYDAY=${eventForm.value.rrule.byDay.join(',')}`);
      }

      if (eventForm.value.rrule.byMonthDay !== null) {
        rruleParts.push(`BYMONTHDAY=${eventForm.value.rrule.byMonthDay}`);
      }

      if (eventForm.value.rrule.until) {
        rruleParts.push(`UNTIL=${eventForm.value.rrule.until.replace(/-/g, '')}`);
      }

      if (eventForm.value.rrule.wkst) {
        rruleParts.push(`WKST=${eventForm.value.rrule.wkst}`);
      }

      const rruleStr = rruleParts.join(';');

      const userInfo = canUserInformation.getUserInfo();

      // 创建事件对象
      const newEvent = {
        id: Math.floor(Math.random() * 10000), // 随机生成 ID
        title: eventForm.value.title,
        start: eventForm.value.start,
        end: eventForm.value.end,
        description: eventForm.value.description,
        userId: userInfo.id,
        rrule: rruleStr
      };

      // 将 newEvent 添加到你的事件列表中
      console.log('新事件:', newEvent);
      calendarApp.value.eventsService.add(newEvent)
      try{
        // 发送POST请求
        const response = axios.post('http://localhost:8080/calendarEvent/add', newEvent, {
          headers: {
            'Content-Type': 'application/json'
          }
        });
      }catch(error){
        console.error('Error:', error);
      }
      // 清空表单并关闭对话框
      formRef.value.resetFields();
      dialogVisible.value = false;
    } else {
      console.log('表单验证失败');
      return false;
    }
  });
};


const getAllEvents = async () => { 
  console.log(events.value)
  const userInfo = canUserInformation.getUserInfo();
  const url = `http://localhost:8080/calendarEvent/getAll?userId=${userInfo.id}` 
  try { 
    const response = await axios.get(url)
    events.value = response.data.data || []
    console.log('获取所有事件成功:', events.value)
    const originalEvents = calendarApp.value.eventsService.getAll();
    for (let i = 0; i < originalEvents.length; i++){
      calendarApp.value.eventsService.remove(originalEvents[i].id)
    }
    for (let i = 0; i < events.value.length; i++){
      calendarApp.value.eventsService.add(events.value[i])
    }
  }catch (error) { 
    console.error('获取所有事件失败:', error) 
  }
};

const getLearningResources = async () => { 
  canButtonVisible.setButtonVisible(false)
  canDrawerVisible.setDrawerVisible(true)
  const prompt = `根据我面试过程中出现的以下三个方面的问题，给我推荐一些提高的网址、网站或者视频，以及一些面试技巧，有加油鼓励的话。表情方面：${expressionAnalysis}。语音方面：${voiceEvaluation}。知识掌握方面：${masteryOfKnowledge}`;
  const disPlayPrompt = `根据我的面试结果给我推荐一些提高学习的网站或者视频`;
  canChatWithAIStore.setChatWithAI(prompt);
  canChatWithAIStore.setDisplayChatWithAI(disPlayPrompt);
};

// 声明全局变量
declare const VisGraph: any;

const graphPanel = ref<HTMLDivElement | null>(null);

const config = {
  node: {
    label: {
      show: true,
      color: '0,0,0',
      font: 'normal 25px KaiTi',
      textPosition: 'Middle_Center'
    },
    shape: 'circle',
    width: 120,
    height: 120,
    color: '80,200,255',
    borderWidth: 0,
    selected: {
      borderColor: '255,0,0',
      borderAlpha: 0.8,
      borderWidth: 8
    }
  },
  link: {
    label: {
      show: true,
      color: '50,50,50',
      font: 'normal 12px KaiTi'
    },
    lineType: 'direct',
    colorType: 'defined',
    color: '0,0,0',
    alpha: 1,
    lineWidth: 3,
    lineDash: [0],
    showArrow: true
  },
  wheelZoom: 1,
  highLightNeiber: false
}

let visgraph: any;

const graphData = ref({ nodes: [], links: [] });

const generateGraphData = () => {
  // 查找根节点数据
  const rootNodeData = graphData.value.nodes.find(node => node.id === '0');

  // 如果没有找到根节点数据，则输出警告并返回
  if (!rootNodeData) {
    console.warn('找不到id为 0 的根节点数据');
    return;
  }

  // 添加根节点
  const rootNode = visgraph.addNode({
    id: rootNodeData.id,
    label: rootNodeData.label,
    type: rootNodeData.type,
    x: 500,
    y: 300,
    color: '100,180,230' // 蓝色
  });

  // 过滤出所有以根节点为父节点的链接
  const rootLinks = graphData.value.links.filter(link => link.source === rootNodeData.id);

  // 遍历这些链接并添加对应的子节点
  rootLinks.forEach((link, index) => {
    // 查找对应的目标节点数据
    const childNodeData = graphData.value.nodes.find(node => node.id === link.target);

    // 如果没有找到对应节点数据，则输出警告并跳过
    if (!childNodeData) {
      console.warn(`找不到id为 ${link.target} 的节点数据`);
      return;
    }

    // 统计当前 childNodeData.id 的子节点数量
    const childCount = graphData.value.links.filter(link => link.source === childNodeData.id).length;

    // 创建一个新的子节点
    const childNode = visgraph.addNode({
      id: childNodeData.id,
      label: childNodeData.label,
      x: 500 + 200 * Math.cos((index * 360) / rootLinks.length * (Math.PI / 180)),
      y: 300 + 200 * Math.sin((index * 360) / rootLinks.length * (Math.PI / 180)),
      color: '173,216,230'
    });

    // 设置一些额外属性
    childNode.tipText = childCount; // 子节点的数量作为 tipText 值
    childNode.alarmColor = visgraph.randomColor();
    childNode.alarmAlpha = 1;

    // 绑定双击事件处理函数
    childNode.dbclick(function (this: any, event: any) {
      if ((this.outLinks || []).length === 0) {
        searchNodeRelations(this);
        this.tipText = null;
      } else {
        if (this.tipText) {
          visgraph.expanded(this);
        } else {
          visgraph.contract(this);
        }
      }
    });

    // 添加从根节点到子节点的连接
    visgraph.addEdge({
      source: rootNode.id,
      target: childNode.id,
      // 可选：设置标签
      // label: `关系${index}`
    });
  });

  // 自动调整缩放级别
  visgraph.setZoom('auto');
  // 自动调整缩放级别
  // visgraph.translateToCenter();
};

const searchNodeRelations = (node: any) => {
  const nodes: any[] = [];
  const links: any[] = [];

  // 查找所有以当前节点为源节点的连接
  const relatedLinks = graphData.value.links.filter(link => link.source === node.id);

  if (!relatedLinks.length) {
    console.log('没有找到相关的子节点');
    return;
  }

  // 遍历所有相关的链接
  relatedLinks.forEach((link, index) => {
    const childNodeData = graphData.value.nodes.find(nodeData => nodeData.id === link.target);
    
    if (!childNodeData) {
      console.warn(`找不到id为 ${link.target} 的节点数据`);
      return;
    }

    // 统计当前 childNodeData.id 的子节点数量
    const childCount = graphData.value.links.filter(link => link.source === childNodeData.id).length;

    // 创建子节点对象
    const childNode = {
      id: childNodeData.id,
      label: childNodeData.label,
      x: node.x + 200 * Math.cos((index * 360) / relatedLinks.length * (Math.PI / 180)),
      y: node.y + 200 * Math.sin((index * 360) / relatedLinks.length * (Math.PI / 180)),
      color: '173,216,230',
      tipText: childCount, // 子节点的数量作为 tipText 值
      // alarmColor: visgraph.randomColor(),
      alarmAlpha: 1
    };

    // 添加节点和链接
    nodes.push(childNode);
    links.push({
      source: node.id,
      target: childNodeData.id,
    });
  });

  // 添加节点和链接到视图
  visgraph.activeAddNodeLinks(nodes, links);

  // 为每个新添加的节点绑定双击事件
  nodes.forEach(childNode => {
    // 从图中获取实际节点对象
    const actualNode = visgraph.nodes.find((n: any) => n.id === childNode.id);
    if (!actualNode) return;
    
    // 绑定双击事件处理函数
    actualNode.dbclick(function (this: any, event: any) {
      if ((this.outLinks || []).length === 0) {
        searchNodeRelations(this);
        this.tipText = null;
      } else {
        if (this.tipText) {
          visgraph.expanded(this);
        } else {
          visgraph.contract(this);
        }
      }
    });
  });
};

const getKnowledgeGraph = async () => {
  try {
    const requestBody = {
      data: `${canInterviewJob.getInterviewJob().jobType}，请根据我上述的不足，展示我需要学习相关的知识`,
      userId: 1
    };
    const url = `http://localhost:8080/knowledgeGraph/getNodesAndLinksByAI`;

    const response = await axios.post(url, requestBody, {
      headers: {
        'Content-Type': 'application/json'
      }
    });

    // console.log('知识图谱数据:', response.data);

    // 提取 nodes 和 links 并组合成符合 JSON 结构的对象
    const { nodes, links } = response.data.data;

    // 将 nodes 和 links 合并到 graphData 中
    graphData.value = {
      nodes: [...nodes],
      links: [...links]
    };
    generateGraphData();

  } catch (error) {
    console.error('获取知识图谱失败:', error);
    return null;
  }
};

onMounted(() => {
  if (graphPanel.value) {
    visgraph = new VisGraph(graphPanel.value, config);
    generateGraphData();

    // 手动为可能触发滚动阻塞的事件添加 passive 选项
    const addPassiveEventListeners = () => {
      const targetElement = graphPanel.value as HTMLElement;
      ['touchstart', 'touchmove', 'mousewheel'].forEach(eventType => {
        targetElement.addEventListener(eventType, event => {
          // 这里可以添加任何你需要的逻辑
          // 注意：不能调用 event.preventDefault()
        }, { passive: true });
      });
    };

    addPassiveEventListeners();
  }
});

const targetedQuestionTraining = async () => { 
  window.open(router.resolve({ name: 'QuestionTraining' }).href, '_blank');
};

const voiceTraining = async () => { 
  window.open(router.resolve({ name: 'SpeechEvaluation' }).href, '_blank');
}; 
</script>

<style scoped>
/* 部分标题 */
.section {
  margin-bottom: 40px;
  background: white;
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
  transition: all 0.3s ease;
}

.section:hover {
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
}

.section-title {
  color: #2c3e50;
  border-left: 4px solid #3498db;
  padding-left: 12px;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 24px;
}
/* 对话框整体样式 */
.custom-event-dialog {
    border-radius: 16px;
  overflow: hidden;
}

/* 标题区域样式 */
.dialog-header {
  display: flex;
  align-items: center;
  padding: 0 0 16px 0;
  margin: 0 0 16px 0;
  border-bottom: 1px solid #f0f0f0;
}

.dialog-title {
  font-size: 20px;
  font-weight: 600;
  color: #2c3e50;
  display: flex;
  align-items: center;
}

.dialog-title::before {
  content: "";
  display: inline-block;
  width: 4px;
  height: 18px;
  background: linear-gradient(to bottom, #409eff, #66b1ff);
  margin-right: 12px;
  border-radius: 2px;
}

/* 表单整体样式 */
.event-form {
  padding: 0 10px;
}

/* 标题输入框样式 */
.title-input :deep(.el-input__inner) {
  height: 30px;
  font-size: 14px;
  border-radius: 8px;
  padding: 8px 12px;
}

/* 时间选择区域 */
.time-section {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
}

.time-item {
  flex: 1;
  margin-bottom: 0;
}

.time-item :deep(.el-form-item__label) {
  font-weight: 500;
  color: #606266;
  padding-right: 8px;
}

.time-picker {
  width: 100%;
}

/* 描述输入框 */
.description-input :deep(.el-textarea__inner) {
  border-radius: 8px;
  padding: 12px;
  min-height: 80px;
}

.msg {
  font-size: 18px;
  text-align: left;
  line-height: 28px;
  padding: 10px;
  max-width: 100%;
  border-radius: 10px;
  background-color: aliceblue;
}

.container {
  top: 0;
  left: 0;
  width: 70vw;
  height: 70vh;
}

.day-select {
  flex: 1;
}

.date-picker {
  flex: 1;
}

/* 提交按钮样式 */
.submit-btn {
  width: 100%;
  height: 40px;
  font-size: 16px;
  border-radius: 8px;
  background-color: #409EFF;
  border: none;
  margin-top: 10px;
}

.submit-btn:hover {
  background-color: #66b1ff;
}
.form-item-with-label :deep(.el-form-item__label) {
  width: 50px !important;
  text-align: left;
  
  font-weight: 500;
  color: #606266;
  padding-right: 12px;
}

/* 调整频率选择器的对齐 */
.frequency-select {
  flex: 1;
  margin-left: 0;
}

/* 调整选项行的对齐 */
.option-row {
  display: flex;
  align-items: center;
  margin-bottom: 16px;
}

.option-label {
  width: 85px;
  font-size: 14px;
  color: #606266;
  text-align: left;
  margin-right: 10px;
}
/* 知识图谱按钮样式 */
.knowledge-graph-btn {
  background: linear-gradient(135deg, #6995ec, #a7c8f6);
  border: none;
  color: white;
  font-weight: bold;
  padding: 12px 24px;
  box-shadow: 0 4px 12px rgba(144, 147, 153, 0.3);
  transition: all 0.3s;
  margin: 0 0 20px auto; /* 修改了这里的margin属性值，使按钮左对齐 */
}

.knowledge-graph-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(144, 147, 153, 0.4);
}

.knowledge-graph-btn .el-icon {
  margin-right: 8px;
  font-size: 16px;
}
/* 部分标题 */
.section {
  margin-bottom: 40px;
  background: white;
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
  transition: all 0.3s ease;
}

.section:hover {
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
}

.section-title {
  color: #2c3e50;
  border-left: 4px solid #3498db;
  padding-left: 12px;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 24px;
}
.sx-vue-calendar-wrapper {
  width: 100%;
  height: 800px;
  max-height: 100vh;
}
.msg {
  font-size: 18px;
  text-align: left;
  line-height: 28px;
  padding: 10px;
  max-width: 100%;
  border-radius: 10px;
  background-color: aliceblue;
}

.graph-panel {
  width: 100%;
  height: 100%;
  background-color: #efefef;
}
</style>